package fencer911;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
 * @author <a href="https://github.com/fencer911/transfer-file-by-qrcode">transfer-file-by-qrcode</a>
 * @since 2020/03
 */
public class FileQrCodeSenderListener {
    private static Future<?> curTask;
    private static String FILE_PATH="";
    private static byte[] data= null;

    private static void showQRCode(byte[] dataBytes,QrConfig config) {
        BufferedImage image=CodeUtils.createQRCode(new String(dataBytes), BarcodeFormat.QR_CODE,config);

        ImagePannel imagePannel=FileQrCodeSenderForm.getInstance().getLeftPanel();
        imagePannel.setBufferedImage(image);
        imagePannel.repaint();
    }
    private static QrConfig getConfig(){
        int imgSize = Integer.parseInt(FileQrCodeSenderForm.getInstance().getImgSizeTextField().getText());
        QrConfig config = new QrConfig(imgSize, imgSize);
        config.setSplitSize(Integer.parseInt(FileQrCodeSenderForm.getInstance().getSplitSizeTextField().getText())) ;
        config.setErrorCorrection((ErrorCorrectionLevel)FileQrCodeSenderForm.getInstance().getErrorComboBox().getSelectedItem());
        config.setInterval(Integer.parseInt(FileQrCodeSenderForm.getInstance().getIntervalTextField().getText()));

        return config;
    }
    private static void chooseImage()  {
        JFileChooser fileChooser = new JFileChooser();
        int approve = fileChooser.showOpenDialog(FileQrCodeSenderForm.getInstance().getRootPanel());
        if (approve == JFileChooser.APPROVE_OPTION) {
            File selectedFile = new File(fileChooser.getSelectedFile().getAbsolutePath());
            if(selectedFile.exists()){
                try {
                    data = FileUtils.readFileToByteArray(selectedFile);
                    FILE_PATH=fileChooser.getSelectedFile().getAbsolutePath();
                    App.app.setTitle(App.APP_NAME+" f:"+FILE_PATH);
                }catch (Throwable err){
                    JOptionPane.showMessageDialog( App.app,"read file:"+FILE_PATH+" occur error! "+err.getMessage());
                    return ;
                }
            }else{
                App.app.setTitle(App.APP_NAME);
            }
        }else{
            FILE_PATH="";
            data=null;
        }
    }
    public static Runnable showQRCodeBatch(byte[] data, String textArea, final QrConfig config){
        final byte[][] dataArray=new Encoder().encode(data, config.splitSize);//encode in  QRCODE GIF FILE.
        final int total=dataArray.length;
        final int sleep=config.getInterval();

        final List<Integer> indexIds=new ArrayList<Integer>(2);
        String[] indexSpan=textArea.split(",");
        for(String id:indexSpan) {
            try {
                indexIds.add(Integer.parseInt(id));
            }catch(Throwable e1){
                continue;
            }
        }
        //
        int start=0;
        int end=total-1;
        boolean sequentialScan=true;
        if(indexIds!=null){
            if(indexIds.size()==2){
                start=indexIds.get(0);
                end=indexIds.get(1);
            }else{
                if(indexIds.size()>=3) {
                    sequentialScan = false;
                    start=0;
                    end=indexIds.size()-1;
                }
            }
        }

        final int finalStart = start;
        final int finalEnd = end;
        final boolean finalSequentialScan = sequentialScan;
        System.out.println(finalStart+","+finalEnd+" "+finalSequentialScan+" sleep:"+sleep);
        if(finalSequentialScan)
            FileQrCodeSenderForm.getInstance().getTextArea().setText(finalStart+","+end);

        Runnable taskRun=new Runnable(){
            @Override
            public void run() {
                while(true) {
                    for (int i = finalStart; i <= finalEnd; ++i) {
                        if(!Thread.currentThread().isInterrupted()) {//do work
                            int realIndex=finalSequentialScan?i:indexIds.get(i);
                            FileQrCodeSenderForm.getInstance().getTipLabel().setText("Tips:" + total + "/" + realIndex);
                            showQRCode(Base64.encodeBase64(dataArray[realIndex]), config);
                        }else{// thread exit
                            return;
                        }
                        try {// sleep for wait receiver process
                            Thread.sleep(sleep);
                        } catch (InterruptedException interruptedException) {
                            System.out.println("interruptedException"+Thread.currentThread().isInterrupted());
                            Thread.currentThread().interrupt();
                            System.out.println("interrupted"+Thread.currentThread().isInterrupted());
                        }
                    }
                }
            }
        };
        return taskRun;
    }
    public static void addListeners() {
        FileQrCodeSenderForm.getInstance().getTransModeFileRBtn().addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                chooseImage();
            }
        });
        FileQrCodeSenderForm.getInstance().getGenButton().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("curTask:"+curTask+" genBtn:"+FileQrCodeSenderForm.getInstance().getGenButton().getText());
                if(curTask!=null){
                    curTask.cancel(true);
                    System.out.println("cancel task:"+curTask);
                }
                    QrConfig config = getConfig();
                    String textAreaStr = FileQrCodeSenderForm.getInstance().getTextArea().getText().trim();
                    if (!FileQrCodeSenderForm.getInstance().getTransModeFileRBtn().isSelected()){
                        byte[] dataText = textAreaStr.getBytes();
                        int maxSize=Integer.parseInt(FileQrCodeSenderForm.getInstance().getMaxSizeTextField().getText().trim());
                        if (dataText.length <=maxSize ) {
                            showQRCode(dataText, config);
                        } else {
                            JOptionPane.showMessageDialog(App.app, "The text's size too big >"+maxSize+"(Max-Text-Size)!It will transfer the text as a text file!", "too big", JOptionPane.OK_CANCEL_OPTION);
                            FileQrCodeSenderForm.getInstance().getTransModeFileRBtn().setSelected(true);//set fileMode
                            data = dataText;//source is textArea
                        }
                    }
                    if (FileQrCodeSenderForm.getInstance().getTransModeFileRBtn().isSelected())
                    {
                        if (FileQrCodeSenderForm.getInstance().getGenButton().getText().equals("Pause")) {//click pause =stop  status:pause->Generate
                            FileQrCodeSenderForm.getInstance().getGenButton().setText("Generate");
                            return;
                        } else {// click Generate=showQRCode  status: Generate->Pause
                            FileQrCodeSenderForm.getInstance().getGenButton().setText("Pause");
                            Runnable taskRun=showQRCodeBatch(data, textAreaStr, config);
                            curTask=App.executor.submit(taskRun);
                        }
                    }
                    System.out.println("create task:"+curTask);
            }
        });
    }
}
